/* 
 * File:   client.c
 *
 */

#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>

#define MAX_LINE 100
// 3 caracteres pour les codes ASCII 'cr', 'lf' et '\0'
#define LINE_ARRAY_SIZE (MAX_LINE+3)

int main() {

  int socketDescriptor;
  int numRead;
  unsigned short int serverPort;
  struct sockaddr_in serverAddress;
  struct hostent *hostInfo;
  struct timeval timeVal;
  fd_set readSet;
  char buf[LINE_ARRAY_SIZE], c, nomFichier[LINE_ARRAY_SIZE], temp[LINE_ARRAY_SIZE];
  FILE *fichier;
  int debutFichier;

  printf("Entrez le nom du serveur ou son adresse IP: ");

  memset(buf, 0x0, LINE_ARRAY_SIZE);  // Mise a zero du tampon
  strcpy(buf,"127.0.0.1");
  //scanf("%s", &buf);
  // gethostbyname() recoit un nom d'hote ou une adresse IP en notation
  // standard 4 octets en decimal separes par des points puis renvoie un
  // pointeur sur une structure hostent. Nous avons besoin de cette structure
  // plus loin. La composition de cette structure n'est pas importante pour
  // l'instant.
  hostInfo = gethostbyname(buf);
  if (hostInfo == NULL) {
    printf("Probleme: ne peut determiner l'adresse du serveur: %s\n", buf);
    exit(1);
  }

  printf("Entrez le numero de port du serveur: ");
  serverPort = 8888;
  //scanf("%i", &serverPort);
  // Cr�ation de socket. "AF_INET" correspond � l'utilisation du protocole IPv4
  // au niveau r�seau. "SOCK_DGRAM" correspond � l'utilisation du protocole UDP
  // au niveau transport. La valeur 0 indique qu'un seul protocole sera utilis�
  // avec ce socket.
  socketDescriptor = socket(AF_INET, SOCK_DGRAM, 0);
  if (socketDescriptor < 0) {
    printf("Probleme: ne peut creer le connecteur logique (socket).\n");
    exit(1);
  }

  // Initialisation des champs de la structure serverAddress
  serverAddress.sin_family = hostInfo->h_addrtype;
  memcpy((char *) &serverAddress.sin_addr.s_addr,
         hostInfo->h_addr_list[0], hostInfo->h_length);
  serverAddress.sin_port = htons(serverPort);

  printf("\nEntrez un nom de fichier pour envoyer au serveur.\n");
  printf("\nEntrez 'quit' pour eteindre le serveur.\n");
	printf("\nEntrez '.' pour fermer le client.\n");

  // Invite de commande pour l'utilisateur et lecture des caract�res jusqu'� la
  // limite MAX_LINE. Puis suppression du saut de ligne.
  printf("Fichier: ");
  memset(buf, 0x0, LINE_ARRAY_SIZE);  // Zero out the buffer.
  scanf("%s", &nomFichier);

  // Arr�t lorsque l'utilisateur saisit une ligne ne contenant qu'un point
  while (strcmp(nomFichier, ".")) {
    
     fichier = fopen (nomFichier, "rt");  /* open the file for reading */

	debutFichier = 1;
	 
     while(fgets(buf, 99, fichier) != NULL){
	 
		if(debutFichier == 1){
			sprintf(&temp[0], "%c", 1);
			strcat(temp, buf);
			strcpy(buf,temp);
			debutFichier = 0;
		}
    	// Envoi de la ligne au serveur
        if (sendto(socketDescriptor, buf, strlen(buf), 0,(struct sockaddr *) &serverAddress,sizeof(serverAddress)) < 0) {
          printf("Probleme: ne peut transmettre les donnees.");
          close(socketDescriptor);
          exit(1);
        }
    	 
    	 // Attente de la reponse pendant une seconde.
        FD_ZERO(&readSet);
        FD_SET(socketDescriptor, &readSet);
        timeVal.tv_sec = 20;
        timeVal.tv_usec = 0;

        if (select(socketDescriptor+1, &readSet, NULL, NULL, &timeVal)) {
            // Lecture de la ligne modifi�e par le serveur.
            memset(buf, 0x0, LINE_ARRAY_SIZE);  // Mise � z�ro du tampon
            numRead = recv(socketDescriptor, buf, MAX_LINE, 0);
            if (numRead < 0) {
              printf("Probleme: pas de reponse du serveur.");
              close(socketDescriptor);
              exit(1);
            }
      			if((int)buf[0] == 6){
      				printf("Reussit!\n");
      			} else if((int)buf[0] == 19){
			    printf("Serveur Plein! ... Mise en attente\n");
			    //sleep(10);
			    memset(buf, 0x0, LINE_ARRAY_SIZE);
			    while((int)buf[0] != 17){
				    recv(socketDescriptor, buf, MAX_LINE, 0);
			    }
			}else{
      				printf("Le serveur n'a pas bien recu!  ---%d\n",(int)buf[0]);
      			}
          
        } else {
          printf("** Le serveur n'a pas repondu apres 1 seconde.\n");
        }
  	 
  	 
     }
     fclose(fichier);  /* close the file prior to exiting the routine */
		
		
	// Envoi du ETX BCC EOT
	memset(buf, 0x0, LINE_ARRAY_SIZE);  // Mise a zero du tampon
	sprintf(&buf[0], "%c", 3);
	sprintf(&buf[1], "%c", 's'); //checksum caracter
	sprintf(&buf[2], "%c", 4);
	if (sendto(socketDescriptor, buf, strlen(buf), 0,(struct sockaddr *) &serverAddress,sizeof(serverAddress)) < 0) {
	  printf("Probleme: ne peut transmettre les donnees.");
	  close(socketDescriptor);
	  exit(1);
	}
	 
	 // Attente de la reponse pendant une seconde.
	FD_ZERO(&readSet);
	FD_SET(socketDescriptor, &readSet);
	timeVal.tv_sec = 20;
	timeVal.tv_usec = 0;

	if (select(socketDescriptor+1, &readSet, NULL, NULL, &timeVal)) {
		// Lecture de la ligne modifie par le serveur.
		memset(buf, 0x0, LINE_ARRAY_SIZE);  // Mise a zero du tampon
		numRead = recv(socketDescriptor, buf, MAX_LINE, 0);
		if (numRead < 0) {
		  printf("Probleme: pas de reponse du serveur.");
		  close(socketDescriptor);
		  exit(1);
		}
		if((int)buf[0] == 6){
			printf("Reussit!\n");
		}
	}else{
		printf("Le serveur n'a pas bien recu!  ---%d\n",(int)buf[0]);
	}
		
		
      // Invite de commande pour l'utilisateur et lecture des caract�res jusqu'� la
      // limite MAX_LINE. Puis suppression du saut de ligne. Comme ci-dessus.
      printf("Fichier: ");
      memset(buf, 0x0, LINE_ARRAY_SIZE);  // Mise � z�ro du tampon
      scanf("%s", nomFichier);
  }

    close(socketDescriptor);
      return (EXIT_SUCCESS);
}
